package com.ysstech.etfmanage.service.impl;

import java.util.*;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysstech.common.cache.MapCacheManager;
import com.ysstech.common.cache.RedisCacheManager;
import com.ysstech.common.entity.PageBean;
import com.ysstech.common.service.HolidayService;
import com.ysstech.common.util.DateUtil;
import com.ysstech.etfmanage.entity.Account;
import com.ysstech.etfmanage.entity.AccountFill;
import com.ysstech.etfmanage.entity.ParamVo;
import com.ysstech.etfmanage.enums.EtfManageEnum;
import com.ysstech.etfmanage.feign.FeignValuationService;
import com.ysstech.etfmanage.feign.entity.Quotation;
import com.ysstech.etfmanage.mapper.AccountMapper;
import com.ysstech.etfmanage.service.AccountFillService;
import com.ysstech.etfmanage.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lishuangliang
 * @since 2021-02-10
 */
@Slf4j
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {

    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private AccountFillService accountFillService;
    @Autowired
    private FeignValuationService feignValuationService;
    @Autowired
    private HolidayService holidayService;
    @Autowired
    private RedisCacheManager redisCacheManager;

    @Override
    public PageBean<Account> queryAllEtfaccount(Account vo, PageBean pageBean) throws Exception {
        QueryWrapper<Account> wrapper = this.getQueryWrapper(vo);
        IPage<Account> pageAccount = accountMapper.queryEtfAccount(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()), wrapper);
        this.switchedListEtfaccount(pageAccount.getRecords());
        return new PageBean<>(pageAccount);
    }

    /**
     * 类型等中文的转换
     *
     * @param list
     * @return
     * @throws Exception
     */
    public List<Account> switchedListEtfaccount(List<Account> list) throws Exception {
        for (Account account : list) {
            if (null == account) {
                continue;
            }
        }
        return list;
    }

    /**
     * 查询条件
     *
     * @param account
     * @return
     * @throws Exception
     */
    private QueryWrapper<Account> getQueryWrapper(Account account) throws Exception {
        QueryWrapper<Account> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("BUSINESS_TYPE,FDATE,SECURITY_CODE,SHAREHOLDER_CODE,TRANSACTION_NUMBER");
        if (null == account) {
            return wrapper;
        }
        if (StringUtils.isNotBlank(account.getStartDate())) {
            wrapper.ge("FDATE", account.getStartDate());
        }
        if (StringUtils.isNotBlank(account.getEndDate())) {
            wrapper.le("FDATE", account.getEndDate());
        }
        //证券代码
        if (StringUtils.isNotBlank(account.getSecurityCode())) {
            wrapper.like("SECURITY_CODE", account.getSecurityCode());
        }
        // ETF类型
        if (StringUtils.isNotBlank(account.getStrEtfType())) {
            List<String> list = JSONArray.parseArray(account.getStrEtfType(), String.class);
            if (!CollectionUtils.isEmpty(list) && StringUtils.isNotBlank(list.get(0))) {
                wrapper.in("ETF_TYPE", list);
            }
        }
        // 业务类型， 申购，赎回，待买，待卖，必须等
        if (StringUtils.isNotBlank(account.getBusinessType())) {
            List<String> list = JSONArray.parseArray(account.getBusinessType(), String.class);
            if (!CollectionUtils.isEmpty(list) && StringUtils.isNotBlank(list.get(0))) {
                wrapper.in("BUSINESS_TYPE", list);
            }
        }
        // 清算标志
        if (StringUtils.isNotBlank(account.getClearCode())) {
            List<String> list = JSONArray.parseArray(account.getClearCode(), String.class);
            if (!CollectionUtils.isEmpty(list) && StringUtils.isNotBlank(list.get(0))) {
                wrapper.in("CLEAR_CODE", list);
            }
        }
        // ETF模式 1.股票2.债券。3期货
        if (StringUtils.isNotBlank(account.getStrEtfMode())) {
            List<String> list = JSONArray.parseArray(account.getStrEtfMode(), String.class);
            if (!CollectionUtils.isEmpty(list) && StringUtils.isNotBlank(list.get(0))) {
                wrapper.in("ETF_MODE", list);
            }
        }
        // ETF市场
        if (StringUtils.isNotBlank(account.getMarket())) {
            List<String> list = JSONArray.parseArray(account.getMarket(), String.class);
            if (!CollectionUtils.isEmpty(list) && StringUtils.isNotBlank(list.get(0))) {
                wrapper.in("ETF_MODE", list);
            }
        }
        // 明细汇总按照股东代码
        if (StringUtils.isNotBlank(account.getDetailSum())) {
            List<String> list = JSONArray.parseArray(account.getDetailSum(), String.class);
            if (!CollectionUtils.isEmpty(list) && StringUtils.isNotBlank(list.get(0))) {
                if ("1".equals(list.get(0))) {
                    wrapper.eq("SHAREHOLDER_CODE", "*");
                } else {
                    wrapper.ne("SHAREHOLDER_CODE", "*");
                }
            }
        }
        return wrapper;
    }


    /**
     * 查询跨市场券的初始化信息
     *
     * @return
     */
    @Override
    public List<Account> queryStockCrossInitList(Account vo) throws Exception {
        return accountMapper.queryStockCrossInitList(vo);
    }

    /**
     * 查询本市场券的初始化数据
     *
     * @return
     */
    @Override
    public List<Account> queryStockInitList(Account vo) throws Exception {
        return accountMapper.queryStockInitList(vo);
    }

    /**
     * 商品期货类初始化
     *
     * @return
     */
    @Override
    public List<Account> queryFuturesInitList(Account vo) throws Exception {
        return accountMapper.queryFuturesInitList(vo);
    }

    /**
     * 从reids缓存取出来的数据放到map缓存，防止每次都去redis取
     *
     * @param fdate
     * @return
     * @throws Exception
     */
    public Quotation queryQuotation(String fdate, String securityCode) throws Exception {
        Map<String, List<Quotation>> map = null;
        if (!MapCacheManager.getInstance().exists("QUOTATION_" + fdate)) {
            map = feignValuationService.queryQuotationCache(fdate);
            if (CollectionUtils.isEmpty(map)) {
                return null;
            }
            MapCacheManager.getInstance().putCache("QUOTATION_" + fdate, map);
        }
        map = (Map<String, List<Quotation>>) MapCacheManager.getInstance().getCache("QUOTATION_" + fdate);
        if (CollectionUtils.isEmpty(map)) {
            return null;
        }
        List<Quotation> listhq = map.get(fdate + "\t" + securityCode);
        if (CollectionUtils.isEmpty(listhq)) {
            return null;
        }
        Quotation queryQuotation = listhq.get(0);
        if (null == queryQuotation) {
            return null;
        }
        return listhq.get(0);
    }

    /**
     * 查询需要补票的数据 区分T+0 和T+1
     * fdate fsetcode ftype etfMode array（席位号） market tradedate（T+0/T+1）
     *
     * @param vo
     * @param paramVo
     * @return
     */
    @Override
    public List<Account> queryEtfAccountFill(Account vo, ParamVo paramVo) throws Exception {
        QueryWrapper<Account> wrapper = new QueryWrapper<>();
        String date = holidayService.getNextWorkday(vo.getPurchaseDate(), -paramVo.getEtfStartFillDate());
        wrapper.eq("ETF_TYPE", paramVo.getEtfType());
        wrapper.eq("ETF_MODE", paramVo.getEtfMode());
        wrapper.eq("ETF_MARKET", paramVo.getEtfMarket());
        wrapper.eq("ACCOUNT_ID", vo.getAccountId());
        if (StringUtils.isNotBlank(vo.getMarket())) {
            wrapper.eq("MARKET", vo.getMarket());
        }
        wrapper.le("FDATE", DateUtil.strToLocalDate(date));
        wrapper.eq("CLEAR_CODE", EtfManageEnum.ETF_CLEAR_CODE_NO.getCode());
        wrapper.orderByAsc("FDATE,SECURITY_CODE,TRANSACTION_NUMBER,SHAREHOLDER_CODE");
        List<Account> list = this.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        List<String> idlist = new ArrayList<>();
        for (Account account : list) {
            idlist.add(account.getId());
        }
        QueryWrapper<AccountFill> wrapperFill = new QueryWrapper<>();
        wrapperFill.in("ACCOUNT_ID", idlist);
        List<AccountFill> listFill = accountFillService.list(wrapperFill);
        Map<String, List<AccountFill>> map = etfhandleDataEtfaccountFill(listFill);
        // 获取当天的行情信息
        for (Account account : list) {
            if (null == account || StringUtils.isBlank(account.getSecurityCode())) {
                continue;
            }
            if (map.containsKey(account.getId())) {
                account.setListAccountFill(map.get(account.getId()));
            }
            account.setPurchaseDate(vo.getPurchaseDate());
            account.setQuotation(this.queryQuotation(vo.getPurchaseDate(), account.getSecurityCode()));
        }
        return list;
    }

    /**
     * 将待补的一个券拆分成 按照申购日期的集合，分别去补
     *
     * @param list
     * @return
     */
    private Map<String, List<AccountFill>> etfhandleDataEtfaccountFill(List<AccountFill> list) throws Exception {
        Map<String, List<AccountFill>> map = new LinkedHashMap<>();
        if (CollectionUtils.isEmpty(list)) {
            return map;
        }
        for (AccountFill fill : list) {
            if (null == fill) {
                continue;
            }
            String key = fill.getAccountId();
            List<AccountFill> listFill = null;
            if (map.containsKey(key)) {
                listFill = map.get(key);
                if (CollectionUtils.isEmpty(listFill)) {
                    continue;
                }
                listFill.add(fill);
                map.put(key, listFill);
            } else {
                listFill = new ArrayList<>();
                listFill.add(fill);
                map.put(key, listFill);
            }
        }
        return map;
    }


}
